﻿using System;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using TestCommonWindow.Common;
using TestCommonWindow.Interface;
using TestCommonWindow.Model;
using TestCommonWindow.ViewModel;
using TestCommonWindow.Helpers;
using System.IO;

namespace TestCommonWindow.TestApi
{
    public class Darwin : ITestApi
    {
        private LoaderEngine.LoaderEngine _engine;

        public Darwin(LoaderEngine.LoaderEngine engine)
        {
            _engine = engine;
        }

        //事件
        public event Action<string, Brush,int> AppendProcessLogEvent;
        public event Action ShowProduceStatisticsPieChartEvent;

        //检查通信状态
        public bool CheckConnect(string emuName)
        {
            return _engine?.SetInterface(emuName) ?? false;
        }

        //开始测试
        public async Task StartTestAsync(MainViewModel main)
        {
            StringBuilder testRecord = new StringBuilder();//单条测试记录
            Stopwatch watch = new Stopwatch(); //记录测试时间
            try
            {
                //判断本地报告有没有打开
                BusinessProcess.IsFileInUse(Path.Combine(GlobalInfo.reprotSaveDirectory, string.Format("Summary_{0}.csv", DateTime.Now.ToString("yyyyMMdd"))));
                //显示加载动画
                main.IsVisibleLoading = Visibility.Visible;
                //禁用开始按钮防止多次点击
                main.IsEnabledTestButton = false;
                main.TestButtonContent = "正在测试...";
                main.TestStatusBackground = Brushes.White;
                main.TestStatusContent = "";
                GlobalInfo.manualResetEvent_Testing.Reset();//设置无信号，阻塞监听子线程
                GlobalInfo.StartTestingToken = true;
                //清除过程信息
                main.ClearLog = false;
                main.ClearLog = true;
                await Task.Run(()=>
                {
                    watch.Start();
                    //设置时钟频率
                    _engine.CommDevice.Frequency_Hz= 52000000;//如果是null则设置默认值，反之实际的值。
                    //声明测试结果实体类
                    var resultEntity = new TestResult() { Result="PASS"};
                    resultEntity.AppVersion = _engine?.LoaderReleaseVersion; //软件版本信息
                    var arrayChipsetNames = _engine.GetChipsetNamesAvailable();
                    if (arrayChipsetNames.Length == 0)
                    {
                        AppendProcessLogEvent("未查询到Chipset", Brushes.Red,14);
                        return;
                    }
                    string strChipset = arrayChipsetNames.First();
                    //添加Chipset到测试结果实体Other中
                    resultEntity.TestItem += strChipset + "|";
                    _engine.ActiveChipset = strChipset;
                   
                    Application.Current.Dispatcher.BeginInvoke((Action)(() => { main.ChipsetInfo = strChipset; }));
                    AppendProcessLogEvent("Chipset【" + strChipset + "】", Brushes.Black,12);
                    AppendProcessLogEvent("设置ActiveChipset成功", Brushes.Black,12);
                    var arrayFamilyNames = _engine.GetFamilyNamesOfCurrentChipset();
                    if (arrayFamilyNames.Length == 0)
                    {
                        AppendProcessLogEvent("未查询到FamilyNames", Brushes.Red,14);
                        return;
                    }
                    string strFamilyName = arrayFamilyNames.First();
                    //添加FamilyName到测试结果实体中
                    resultEntity.TestItem += strFamilyName + "|";
                    _engine.ActiveFamily = strFamilyName;
                    Application.Current.Dispatcher.BeginInvoke((Action)(() => { main.FamilyInfo = strFamilyName; }));
                    AppendProcessLogEvent("FamilyName【" + strFamilyName + "】", Brushes.Black,12);
                    AppendProcessLogEvent("设置ActiveFamily成功", Brushes.Black,12);
                    var partConfig = GlobalInfo.AppConfigs.EmulatorInfos.First(e => e.Name == main.EmulatorName).PartInfos.First(p => p.PartNumber == main.PartNumber);
                    //设置时间频率的同时要勾选开关Read at Half Speed
                    _engine.FNOperatingMode.SetOperatingMode("HALF_RATE_READ=TRUE");
                    //添加产品信息到测试结果实体中
                    resultEntity.TestItem += partConfig.PartNumber + "|";
                    byte productSlaveAddress = _engine.SlaveAddress;
                    if (productSlaveAddress!=Convert.ToByte(main.SlaveAddress.Split('-')[0]))
                    {
                        AppendProcessLogEvent(string.Format("产品的USID地址【{0}】和选择的地址【{1}】不一致,请选择正确的地址并做好分类",productSlaveAddress,main.SlaveAddress.Split('-')[0]), Brushes.Red, 13);
                        return;
                    }
                    //_engine.SetSlaveAddress(6); //根据不同产品改变USID地址
                    do
                    {
                        foreach (var r in partConfig.RegisterInfos)
                        {
                            //指定寄存器地址十进制值
                             var registerValue = _engine.ReadRegisterInt(Convert.ToInt32(r.Address, 16));
                            //send command fail
                            if (registerValue == -9999)
                            {
                                AppendProcessLogEvent("Failed to find any device connected!", Brushes.Red,14);
                                return;
                            }
                            //转换成八位二进制 110110-->00110110
                            var eightBitBinaryValue = Convert.ToString(registerValue, 2).PadLeft(8, '0');
                            //将8位二进制每一位转换转换成字符数组 {'0','0','1','1','0','1','1','0'}
                            var eightBitBinaryCharArray = eightBitBinaryValue.ToCharArray();
                            StringBuilder testItemBinaryCharValue = new StringBuilder(4);
                            //由于每个测试项对应8位中的不同位，所以根据指定的起始位和结束位提取测试项的值。
                            for (int i = r.StartBitField; i <= r.StopBitField; i++)
                            {
                                testItemBinaryCharValue.Append(eightBitBinaryCharArray[i]);
                            }
                            //测试项十进制值
                            var testItemIntValue = Convert.ToInt32(testItemBinaryCharValue.ToString(), 2);

                            if (r.IsTestItem)
                            {
                                resultEntity.TestItem += string.Format("{0}|{1}|{2}|{3}|{4}|", r.RegisterName, r.Description, r.UpperLimit, r.LowerLimit, testItemIntValue);
                                if (testItemIntValue < r.LowerLimit || testItemIntValue > r.UpperLimit)
                                {
                                    resultEntity.Result = "FAIL";
                                    GlobalInfo.FailCount++;
                                    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                                    {
                                        main.TestStatusBackground = Brushes.Red;
                                        main.TestStatusContent = string.Format("{0} FAIL ", r.Description);
                                    }));
                                    break; //其中有一项不良，下面的测试项就不用测试了，直接退出。
                                }
                                else
                                {
                                    resultEntity.Result = "PASS";
                                    AppendProcessLogEvent(string.Format("{0}:{1}", r.Description, testItemIntValue),Brushes.Black,12);
                                }
                            }
                            else
                            {
                                resultEntity.TestItem += string.Format("{0}|{1}|{2}|", r.RegisterName, r.Description, testItemIntValue);
                            }
                        }
                    } while (false);
                    resultEntity.TestTime = DateTime.Now.ToString("yyyyMMdd HH:mm:ss");
                    AppendProcessLogEvent(string.Format("测试总时间:{0}ms", watch.ElapsedMilliseconds.ToString()), Brushes.Black,12);
                    if (resultEntity.Result == "PASS")
                    {
                        Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                        {
                            main.TestStatusBackground = Brushes.Green;
                        }));
                        GlobalInfo.PassCount++;
                        AppendProcessLogEvent("-----------------Test Result PASS----------------------", Brushes.Green, 20);
                    }
                    else
                    {
                        AppendProcessLogEvent("-----------------Test Result FAIL----------------------", Brushes.Red, 20);
                    }
                    resultEntity.TotalTime = (int)watch.ElapsedMilliseconds;
                    resultEntity.Computer = Environment.MachineName;
                    //显示图表
                    ShowProduceStatisticsPieChartEvent?.Invoke();
                    //保存本地Log
                    var saveDataStatus=BusinessProcess.SaveReport(resultEntity);
                    if (!saveDataStatus)
                    {
                        MessageBox.Show("保存原始Log失败","软件温馨提示!",MessageBoxButton.OK,MessageBoxImage.Error);
                    }
                });
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);//record log
                MessageBox.Show(ex.Message, "软件温馨提示!", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                main.IsVisibleLoading = Visibility.Collapsed;
                main.IsEnabledTestButton = true;
                main.TestButtonContent = "开始测试";
                GlobalInfo.StartTestingToken = false;
                GlobalInfo.manualResetEvent_Testing.Set();//设置有信号，非阻塞状态
            }
        }
        //切换USID从地址
        public bool ToggleSlaveAddress(byte slaveAddress)
        {
            string strChipsetName = _engine.GetChipsetNamesAvailable().First();
            _engine.ActiveChipset = strChipsetName;
            string strFamily = _engine.GetFamilyNamesOfCurrentChipset().First();
            _engine.ActiveFamily = strFamily;
            return _engine.SetSlaveAddress(slaveAddress);
        }
    }
}